﻿/*
 *Author: Jeff Liu 
 *
 *Under MIT License
 *jebberwocky@gmail.com
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CtpGglMap.Impl
{
    /// <summary>
    ///  @since 1.0.0
    /// </summary>
    public class GBounds: IMapItem
    {
        protected double min_lng;
        protected double min_lat;
        protected double max_lng;
        protected double max_lat;

        public GeoPoint Center
        {
            get
            {
                return new GeoPointImpl(
                    (max_lat + min_lat) / 2,
                    (max_lng + min_lng) / 2);
            }
        }

        /// <summary>
        /// Contruct from list of IMapItem
        /// </summary>
        /// <param name="items"></param>
        public GBounds(List<IMapItem> items)
        {
            List<GeoPoint> points = new List<GeoPoint>();
            foreach (IMapItem item in items)
            {
                if (item != null)
                {
                    if (item.GetType() == typeof(GMarker) || item.GetType().IsSubclassOf(typeof(GMarker)))
                    {
                        GMarker marker = item as GMarker;
                        points.Add(marker.Point);
                    }
                }
            }
            this.__constructor(points);
        }

        /// <summary>
        /// Construct from list of GeoPoint
        /// </summary>
        /// <param name="points"></param>
        public GBounds(List<GeoPoint> points)
        {
            this.__constructor(points);
        }

        private void __constructor(List<GeoPoint> points)
        {
            if (points.Count < 1)
                return;
            else
            {
                GeoPoint point = points[0];
                min_lat = point.Lat;
                min_lng = point.Lng;
                max_lat = point.Lat;
                max_lng = point.Lng;
            }

            foreach (GeoPoint point in points)
            {
                if (point.Lng < this.min_lng)
                {
                    min_lng = point.Lng;
                }
                if (point.Lng > this.max_lng)
                {
                    max_lng = point.Lng;
                }
                if (point.Lat < this.min_lat)
                {
                    min_lat = point.Lat;
                }
                if (point.Lat > this.max_lat)
                {
                    max_lat = point.Lat;
                }
            }
        }

        /// <summary>
        /// the north east bound
        /// </summary>
        public GeoPoint NEBound
        {
            get
            {
                GeoPoint point = new GeoPointImpl(max_lat, max_lng);
                return point;
            }
        }

        /// <summary>
        /// the south west bound
        /// </summary>
        public GeoPoint SWBound
        {
            get
            {
                GeoPoint point = new GeoPointImpl(min_lat, min_lng);
                return point;
            }
        }

        /// <summary>
        /// the point is contained in or not
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public bool Contains(GeoPoint point)
        {
            bool v = false;
            if (point != null)
            {    
                if ((this.max_lat > point.Lat && this.min_lat < point.Lat) &&
                    (this.max_lng > point.Lng && this.min_lng < point.Lng))
                {
                    v = true;
                }
            }
            return v;
        }

        /// <summary>
        /// the bound is contained in or not
        /// </summary>
        /// <param name="bounds"></param>
        /// <returns></returns>
        public bool Contains(GBounds bounds)
        {
            bool v = false;
            if (this.Contains(bounds.SWBound) &&
                this.Contains(bounds.NEBound))
            {
                v = true;
            }
            return v;
        }

        /// <summary>
        /// get the GPath from Bound
        /// </summary>
        /// <returns></returns>
        public GPath GetPath()
        {
            throw new NotImplementedException();
        }

        #region IMapItem Members

        public void SetMap(IMap map)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}
